﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using IPC.Communication.Framework.BasicFramework;
using IPC.Communication.Framework.Core.Net;

namespace IPC.Communication.Framework.Profinet.Omron
{
    public class OmronFinsUdpServer : OmronFinsServer
    {
        private int _receiveCacheLength = 2048;

        public int ReceiveCacheLength
        {
            get;
            set;
        }


        public override void ServerStart(int port)
        {
            if (!base.IsStarted)
            {
                StartInitialization();
                CoreSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                CoreSocket.Bind(new IPEndPoint(IPAddress.Any, port));
                RefreshReceive();
                base.IsStarted = true;
                base.Port = port;
                if (base.LogNet != null)
                {
                    base.LogNet.WriteInfo(ToString(), StringResources.Language.NetEngineStart);
                }
            }
        }

        protected override byte[] PackCommand(int status, byte[] finsCore, byte[] data)
        {
            if (data == null)
            {
                data = new byte[0];
            }
            byte[] array = new byte[14 + data.Length];
            SoftBasic.HexStringToBytes("00 00 00 00 00 00 00 00 00 00 00 00 00 00").CopyTo(array, 0);
            if (data.Length != 0)
            {
                data.CopyTo(array, 14);
            }
            array[10] = finsCore[0];
            array[11] = finsCore[1];
            array[12] = BitConverter.GetBytes(status)[1];
            array[13] = BitConverter.GetBytes(status)[0];
            return array;
        }

        private void RefreshReceive()
        {
            AppSession appSession = new AppSession();
            appSession.WorkSocket = CoreSocket;
            appSession.UdpEndPoint = new IPEndPoint(IPAddress.Any, 0);
            appSession.BytesContent = new byte[ReceiveCacheLength];
            CoreSocket.BeginReceiveFrom(appSession.BytesContent, 0, ReceiveCacheLength, SocketFlags.None, ref appSession.UdpEndPoint, AsyncCallback, appSession);
        }

        private void AsyncCallback(IAsyncResult ar)
        {
            AppSession appSession = ar.AsyncState as AppSession;
            if (appSession != null)
            {
                try
                {
                    int num = appSession.WorkSocket.EndReceiveFrom(ar, ref appSession.UdpEndPoint);
                    
                    {
                        RefreshReceive();
                        byte[] array = new byte[num];
                        Array.Copy(appSession.BytesContent, 0, array, 0, num);
                        if (base.LogNet != null)
                        {
                            base.LogNet.WriteDebug(ToString(), "Udp " + StringResources.Language.Receive + "：" + array.ToHexString(' '));
                        }
                        byte[] array2 = ReadFromFinsCore(array.RemoveBegin(10));
                        if (array2 != null)
                        {
                            appSession.WorkSocket.SendTo(array2, array2.Length, SocketFlags.None, appSession.UdpEndPoint);
                            if (base.LogNet != null)
                            {
                                base.LogNet.WriteDebug(ToString(), "Udp " + StringResources.Language.Send + "：" + array2.ToHexString(' '));
                            }
                            RaiseDataReceived(appSession, array);
                        }
                        else
                        {
                            RemoveClient(appSession);
                        }
                    }
                }
                catch (ObjectDisposedException)
                {
                }
                catch (Exception ex2)
                {
                    if (base.LogNet != null)
                    {
                        base.LogNet.WriteException(ToString(), StringResources.Language.SocketEndReceiveException, ex2);
                    }
                    RefreshReceive();
                }
                finally
                {
                }
            }
        }

        public override string ToString()
        {
            return String.Format("OmronFinsUdpServer[{0}]", base.Port);
        }
    }
}
